package com.gangan.shiro.realm;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.gangan.model.Auth;
import com.gangan.model.Role;
import com.gangan.model.User;
import com.gangan.model.view.AuthView;
import com.gangan.service.IApiService;
import com.gangan.service.IAuthService;
import com.gangan.service.IRoleService;
import com.gangan.service.IUserService;
import com.gangan.tools.PasswrodsUtil;
import com.gangan.tools.StringTools;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.set.CompositeSet;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;


/**
 * @author zhengweicheng
 * createTime 2019-01-08
 * shiro用户认证模块。
 */
@Slf4j
public class UserRealm extends AuthorizingRealm {

    public final static String SPACE = ":";

    public final static String ADMIN = "admin";

    @Autowired
    IUserService userService;
    @Autowired
    IRoleService roleService;
    @Autowired
    IApiService apiService;
    @Autowired
    IAuthService authService;
    /**
     * 角色与权限的赋予
     * @param principals
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        String username = (String)principals.getPrimaryPrincipal();
        User result = userService.getOne(Wrappers.<User>query().lambda().eq(User::getLoginname,username));
        if(null == result.getRoleId()){
            return info;
        }
        //根据角色id查询该角色id是否在数据库中存在
        Role role = roleService.getOne(Wrappers.<Role>query().lambda().eq(Role::getRoleId,result.getRoleId()));
        if(null==role){
            return info;
        }
        List<Integer> ids = null != role ? StringTools.resultIntegerArrayBySplitString(role.getRoleAuthIds()) : null;
        //查询权限判断权限内是否有数据
        Set<String> apis = authService.list(Wrappers.<Auth>query().lambda().in(Auth::getAuthId,ids))
                .stream()
                .filter(auth -> AuthView.AUTH_TYPE_BTN.equals(auth.getAuthType()))
                .map(Auth::getParameters).collect(Collectors.toSet());
        info.setStringPermissions(apis);
        return info;
    }

    /**
     * 登录验证
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //根据令牌获取用户名和密码。
        String username = (String) token.getPrincipal();
        String password = new String((char[]) token.getCredentials());
        User result = userService.getOne(new QueryWrapper<User>().eq("loginname",username));
        if(null==result){
            log.info(username+"账户不存在");
            throw new UnknownAccountException();
        }else
            //判断密码是否正确
            if (!PasswrodsUtil.oldOrNewIsEquals(result.getPassword(),password)) {
                log.info("密码不正确");
                throw new IncorrectCredentialsException();
            }else if(result.isDelFlag()){
                log.info("账户已冻结");
                throw new LockedAccountException();
            }
        //移除密码
        result.setPassword(null);
        //将返回的账户密码清除后存入session中
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("user",result);
        return new SimpleAuthenticationInfo(username, password, getName());
    }
}
